package com.atguigu.lease.web.admin.service.impl;

import com.atguigu.lease.model.entity.*;
import com.atguigu.lease.model.enums.ItemType;
import com.atguigu.lease.model.enums.ReleaseStatus;
import com.atguigu.lease.web.admin.globalhandexception.CommonException;
import com.atguigu.lease.web.admin.mapper.ApartmentInfoMapper;
import com.atguigu.lease.web.admin.service.*;
import com.atguigu.lease.web.admin.vo.apartment.ApartmentDetailVo;
import com.atguigu.lease.web.admin.vo.apartment.ApartmentItemVo;
import com.atguigu.lease.web.admin.vo.apartment.ApartmentQueryVo;
import com.atguigu.lease.web.admin.vo.apartment.ApartmentSubmitVo;
import com.atguigu.lease.web.admin.vo.fee.FeeValueVo;
import com.atguigu.lease.web.admin.vo.graph.GraphVo;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @author liubo
 * @description 针对表【apartment_info(公寓信息表)】的数据库操作Service实现
 * @createDate 2023-07-24 15:48:00
 */
@Slf4j
@Service
public class ApartmentInfoServiceImpl extends ServiceImpl<ApartmentInfoMapper, ApartmentInfo> implements ApartmentInfoService {
    @Autowired
    private ApartmentInfoMapper apartmentInfoMapper;
    // 公寓配套表
    @Autowired
    private ApartmentFacilityService apartmentFacilityService;
    //标签信息表
    @Autowired
    private ApartmentLabelService apartmentLabelService;
    // 费用值表
    @Autowired
    private ApartmentFeeValueService apartmentFeeValueService;
    //  公寓图片表
    @Autowired
    private GraphInfoService graphInfoService;
    @Autowired
    private RoomInfoService roomInfoService;
    @Autowired
    private LeaseAgreementService leaseAgreementService;

    /**
     * 保存或更新公寓信息
     *
     * @param apartmentSubmitVo
     */
    @Override
    public void saveOrUpdateApartment(ApartmentSubmitVo apartmentSubmitVo) {
        log.info("保存或更新公寓信息，{}", apartmentSubmitVo);
        //更新表的时候需要id信息，所以id不为空的时候是更新，id为空的时候是新增
        //因为关联的信息比较多，所以更新的时候，给旧数据先删除，再新增新的内容
        //而新增只需要将将新的数据保存到数据库中   所以这样处理不管是新增还是更新都是需要最后新增关联信息表的数据，所以对删除旧数据判断就行了
        //使用saveOrUpdate，先处理主表，再分情况处理关联表
        ApartmentInfo apartmentInfo = new ApartmentInfo();
        BeanUtils.copyProperties(apartmentSubmitVo, apartmentInfo);
        saveOrUpdate(apartmentInfo);
        Long apartmentId = apartmentInfo.getId();
        //当id不为空，说明是更新，需要先删除再新增
        if (apartmentId != null) {
            //删除中间关联表中公寓<->配套相关信息
            apartmentFacilityService.remove(Wrappers.<ApartmentFacility>lambdaQuery().eq(ApartmentFacility::getApartmentId, apartmentId));
            //删除中间关联表中公寓<->标签相关信息
            apartmentLabelService.remove(Wrappers.<ApartmentLabel>lambdaQuery().eq(ApartmentLabel::getApartmentId, apartmentId));
            // 删除公寓图片相关信息(一对多) 类型选择公寓类型
            graphInfoService.remove(Wrappers.<GraphInfo>lambdaQuery()
                    .eq(GraphInfo::getItemType, ItemType.APARTMENT)
                    .eq(GraphInfo::getItemId, apartmentId));
            // 删除费用相关信息
            apartmentFeeValueService.remove(Wrappers.<ApartmentFeeValue>lambdaQuery().eq(ApartmentFeeValue::getApartmentId, apartmentId));
            //注意公寓与区县、城市、省份是多对一关系，所以你新增或者修改直接用的是前端传过来的数据，
            // 在saveOrUpdate(apartmentSubmitVo)中已经完成，所以不需要再进行额外的处理

        }
        //新增关联信息
        //1.插入图片列表
        List<GraphVo> graphVoList = apartmentSubmitVo.getGraphVoList();
        if (!CollectionUtils.isEmpty(graphVoList)) {
            List<GraphInfo> graphInfoList = graphVoList.stream().map(s -> {
                GraphInfo graphInfo = new GraphInfo();
                BeanUtils.copyProperties(s, graphInfo);
                //补充信息
                graphInfo.setItemType(ItemType.APARTMENT);
                graphInfo.setItemId(apartmentId);
                return graphInfo;
            }).collect(Collectors.toList());
            graphInfoService.saveBatch(graphInfoList);
        }


        //2.插入配套与公寓关联之间的关联信息
        List<Long> facilityInfoIdList = apartmentSubmitVo.getFacilityInfoIds();
        if (!CollectionUtils.isEmpty(facilityInfoIdList)) {
            List<ApartmentFacility> facilityList = facilityInfoIdList.stream().map(s -> {
                ApartmentFacility apartmentFacility = new ApartmentFacility();
                //设置对应的公寓id
                apartmentFacility.setApartmentId(apartmentId);
                //设置配套的id
                apartmentFacility.setFacilityId(s);
                return apartmentFacility;
            }).collect(Collectors.toList());
            apartmentFacilityService.saveBatch(facilityList);
        }


        //3.插入标签列表
        List<Long> labelIds = apartmentSubmitVo.getLabelIds();
        if (!CollectionUtils.isEmpty(labelIds)) {
            List<ApartmentLabel> apartmentLabelList = labelIds.stream().map(s -> {
                //创建公寓与标签之间的中间表的实体
                ApartmentLabel apartmentLabel = new ApartmentLabel();
                //绑定关联关系
                apartmentLabel.setApartmentId(apartmentId);
                apartmentLabel.setLabelId(s);
                return apartmentLabel;
            }).collect(Collectors.toList());
            apartmentLabelService.saveBatch(apartmentLabelList);
        }


        //4.插入杂费列表
        List<Long> feeValueIds = apartmentSubmitVo.getFeeValueIds();
        if (!CollectionUtils.isEmpty(feeValueIds)) {
            List<ApartmentFeeValue> apartmentFeeValueList = feeValueIds.stream().map(s -> {
                ApartmentFeeValue apartmentFeeValue = new ApartmentFeeValue();
                apartmentFeeValue.setApartmentId(apartmentId);
                apartmentFeeValue.setFeeValueId(s);
                return apartmentFeeValue;
            }).collect(Collectors.toList());
            apartmentFeeValueService.saveBatch(apartmentFeeValueList);
        }
    }

    /**
     * 根据条件分页查询公寓列表
     * 优化，提升性能
     *
     * @param current
     * @param size
     * @param queryVo
     * @return
     */
    @Override
    public IPage<ApartmentItemVo> pageItem(Long current, Long size, ApartmentQueryVo queryVo) {
        Page<ApartmentInfo> page = new Page<>(current, size);
        IPage<ApartmentItemVo> page1 = apartmentInfoMapper.pageItem(page, queryVo);
        return page1;
    }

    /**
     * 根据条件分页查询公寓列表
     *
     * @return
     */
//    @Override
//    public IPage<ApartmentItemVo> pageItem(Long current, Long size, ApartmentQueryVo queryVo) {
//        Page<ApartmentInfo> page = new Page(current, size);
//        Long provinceId = queryVo.getProvinceId();//省份id
//        Long cityId = queryVo.getCityId();//城市id
//        Long districtId = queryVo.getDistrictId();//区县id
//        Page<ApartmentInfo> apartmentInfoPagepage = lambdaQuery()
//                .eq(provinceId != null, ApartmentInfo::getProvinceId, provinceId)
//                .eq(cityId != null, ApartmentInfo::getCityId, cityId)
//                .eq(districtId != null, ApartmentInfo::getDistrictId, districtId)
//                .orderByDesc(ApartmentInfo::getUpdateTime).page(page);
//        List<ApartmentInfo> records = apartmentInfoPagepage.getRecords();
//        List<ApartmentItemVo> collect = records.stream().map(s -> {
//            ApartmentItemVo apartmentItemVo = new ApartmentItemVo();
//            BeanUtils.copyProperties(s, apartmentItemVo);
//            //查询每个公寓的房间的数量
//            Long count = roomInfoService.lambdaQuery().eq(RoomInfo::getApartmentId, s.getId()).count();
//            //查询空闲的房间数量
//            Long freeCount = roomInfoService.lambdaQuery().eq(RoomInfo::getApartmentId, s.getId()).eq(RoomInfo::getIsRelease, ReleaseStatus.RELEASED).count();
//            Long count1 = leaseAgreementService.lambdaQuery().eq(LeaseAgreement::getApartmentId, s.getId()).in(LeaseAgreement::getStatus, 2, 5).count();
//            apartmentItemVo.setTotalRoomCount(count);
//            apartmentItemVo.setFreeRoomCount(freeCount - count1);
//            return apartmentItemVo;
//        }).collect(Collectors.toList());
//        Page<ApartmentItemVo> apartmentItemVoPage = new Page<>();
//        apartmentItemVoPage.setRecords(collect);
//        apartmentItemVoPage.setTotal(apartmentInfoPagepage.getTotal());
//        return apartmentItemVoPage;
//
////        Page<ApartmentInfo> page = new Page(current, size);
////        IPage<ApartmentItemVo> page1 = apartmentInfoMapper.pageItem(page,queryVo);
////        return page1;
//    }


    @Autowired
    private LabelInfoService labelInfoService;
    @Autowired
    private FacilityInfoService facilityInfoService;
    @Autowired
    private FeeKeyService feeKeyService;
    @Autowired
    private FeeValueService feeValueInfoService;

    /**
     * 根据ID获取公寓详细信息
     *
     * @param id
     * @return
     */
    @Override
    public ApartmentDetailVo getDetailById(Long id) {
        if (id == null) {
            throw new CommonException("公寓ID不能为空");
        }
        ApartmentDetailVo apartmentDetailVo = new ApartmentDetailVo();
        //首先查询出公寓信息
        ApartmentInfo apartmentInfo = this.getById(id);
        if (apartmentInfo == null) {
            throw new CommonException("该公寓不存在");
        }
        BeanUtils.copyProperties(apartmentInfo, apartmentDetailVo);
        //图片列表
        List<GraphInfo> list = graphInfoService.list(Wrappers.<GraphInfo>lambdaQuery()
                .eq(GraphInfo::getItemType, ItemType.APARTMENT)
                .eq(GraphInfo::getItemId, id)
                .select(GraphInfo::getName, GraphInfo::getUrl)
        );
        List<GraphVo> graphVoList = null;
        if (!CollectionUtils.isEmpty(list)) {
            graphVoList = list.stream().map(s -> {
                GraphVo graphVo = new GraphVo();
                BeanUtils.copyProperties(s, graphVo);
                return graphVo;
            }).collect(Collectors.toList());
        }

        //标签列表
        //先从公寓标签中间表获取标签id
        List<ApartmentLabel> list1 = apartmentLabelService.lambdaQuery().eq(ApartmentLabel::getApartmentId, id)
                .select(ApartmentLabel::getLabelId)
                .list();
        List<LabelInfo> labelInfos = null;
        if (!CollectionUtils.isEmpty(list1)) {
            List<Long> labelIds = list1.stream().map(s -> s.getLabelId()).collect(Collectors.toList());
            //再查询标签信息
            labelInfos = labelInfoService.listByIds(labelIds);
        }

        //配套列表
        List<ApartmentFacility> list2 = apartmentFacilityService.lambdaQuery().eq(ApartmentFacility::getApartmentId, id)
                .select(ApartmentFacility::getFacilityId)
                .list();
        List<FacilityInfo> facilityInfos = null;
        if (!CollectionUtils.isEmpty(list2)) {
            List<Long> facilityIds = list2.stream().map(s -> s.getFacilityId()).collect(Collectors.toList());
            facilityInfos = facilityInfoService.listByIds(facilityIds);
        }

        //杂费列表
        List<ApartmentFeeValue> list3 = apartmentFeeValueService.lambdaQuery().eq(ApartmentFeeValue::getApartmentId, id)
                .select(ApartmentFeeValue::getFeeValueId)
                .list();
        List<FeeValueVo> collect = null;
        if (!CollectionUtils.isEmpty(list3)) {
            List<Long> feeValueIds = list3.stream().map(s -> s.getFeeValueId()).collect(Collectors.toList());

            if (!CollectionUtils.isEmpty(feeValueIds)) {
                List<FeeValue> feeValues = feeValueInfoService.listByIds(feeValueIds);
                List<Long> feeKeyIds = feeValues.stream().map(s -> s.getFeeKeyId()).collect(Collectors.toList());
                List<FeeKey> list4 = feeKeyService.listByIds(feeKeyIds);
                collect = list4.stream().map(s -> {
                    FeeValueVo feeValueVo = new FeeValueVo();
                    BeanUtils.copyProperties(s, feeValueVo);
                    return feeValueVo;
                }).collect(Collectors.toList());
            }
        }
        //组合数据返回
        apartmentDetailVo.setGraphVoList(graphVoList);
        apartmentDetailVo.setLabelInfoList(labelInfos);
        apartmentDetailVo.setFacilityInfoList(facilityInfos);
        apartmentDetailVo.setFeeValueVoList(collect);
        return apartmentDetailVo;
    }


//    /**
//     * 根据ID获取公寓详细信息
//     *
//     * @param id
//     * @return
//     */
//    @Override
//    public ApartmentDetailVo getDetailById(Long id) {
//        if (id == null) {
//            throw new CommonException("公寓ID不能为空");
//        }
//        ApartmentDetailVo apartmentDetailVo = apartmentInfoMapper.getDetailById(id);
//        if (apartmentDetailVo == null) {
//            throw new CommonException("该公寓不存在");
//        }
//        return apartmentDetailVo;
//    }

    /**
     * 根据ID删除公寓信息
     *
     * @param id
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void removeApartmentById(Long id) {
        log.info("删除公寓信息开始,{}", id);
        //判断公寓是否有房间，如果有房间则不能删除
        if (roomInfoService.lambdaQuery().eq(RoomInfo::getApartmentId, id).count() > 0) {
            throw new CommonException("先删除房间信息再删除公寓信息");
        }
        //先删除公寓信息
        boolean b = this.removeById(id);
        if (!b) {
            throw new CommonException("删除公寓失败");
        }
        //再删除图片信息
        boolean remove = graphInfoService.remove(Wrappers.<GraphInfo>lambdaQuery()
                .eq(GraphInfo::getItemId, id)
                .eq(GraphInfo::getItemType, ItemType.APARTMENT)
        );

        //删除配套中间表信息
        apartmentFacilityService
                .remove(Wrappers.<ApartmentFacility>lambdaQuery()
                        .eq(ApartmentFacility::getApartmentId, id));

        //删除标签中间表信息
        apartmentLabelService
                .remove(Wrappers.<ApartmentLabel>lambdaQuery()
                        .eq(ApartmentLabel::getApartmentId, id)
                );
        //删除杂费中间表信息
        apartmentFeeValueService
                .remove(Wrappers.<ApartmentFeeValue>lambdaQuery()
                        .eq(ApartmentFeeValue::getApartmentId, id)
                );
    }


    /**
     * 根据ID修改公寓发布状态
     *
     * @param id
     * @param status
     */
    @Override
    public void updateReleaseStatusById(Long id, ReleaseStatus status) {
        ApartmentInfo apartmentInfo = new ApartmentInfo();
        apartmentInfo.setId(id);
        apartmentInfo.setIsRelease(status);
        boolean update = this.updateById(apartmentInfo);
        if (!update) {
            throw new CommonException("修改公寓发布状态失败");
        }
    }

    /**
     * 根据区县ID查询公寓信息列表
     *
     * @param id
     * @return
     */
    @Override
    public List<ApartmentInfo> listInfoByDistrictId(Long id) {
        List<ApartmentInfo> list = lambdaQuery().eq(ApartmentInfo::getDistrictId, id).list();
        return list;
    }

    /**
     * 根据房间ID查询公寓信息
     *
     * @param roomId
     * @return
     */
    @Override
    public ApartmentInfo getInfoById(Long roomId) {
        ApartmentInfo  apartmentInfo = apartmentInfoMapper.getInfoById(roomId);
        return apartmentInfo;
    }
}





